Data Request and Data Response
Overview
In decentralized identity and verifiable credentials, Data Requests and Data Responses allow for secure and privacy-preserving data sharing between two parties (Verifier and Holder).
What is a Data Request?
A Data Request is a request made by a verifier asking a holder to prove certain claims (e.g., age, employment status) using verifiable credentials.
Example: A verifier may request proof of age without needing to see all details on an ID.
What is a Data Response?
A Data Response is the holder’s reply to a data request. It contains cryptographic evidence that proves the validity of the requested claims without exposing unnecessary information.
Example: The holder shares only the proof that they are over 18, without revealing their full date of birth.
Why Use Data Requests/Responses?
- Selective Disclosure: Share only what is needed.
- Security: Cryptographic proofs ensure data integrity.
- Privacy: Protects personal information by sharing minimal data.
Example Use Cases
- Job Applications: Share proof of education.
- Age Verification: Prove age for restricted services.
- Financial Services: Provide proof of income without sensitive details.
Data Request and Response Workflow with One37ID SDK
This guide provides a comprehensive overview of how to manage data requests and data responses using the One37ID SDK. The steps described can handle various types of data requests within the SDK, with the validation process adaptable to different scenarios beyond a driver's license.
Workflow Overview
- Initiate Data Request: The user initiates a validation process for a specific credential.
- SDK Sends Data Request: The SDK sends a
presentationRequestCallback
to obtain the necessary credentials. - Display Data Request to User: The app presents the data request details to the user through a custom UI.
- User Acquires or Submits Credentials: The user provides the required self-attested or verifiable credentials.
- Process Data Response: The SDK validates the submitted credentials and updates the status in the app.
1. Initiate Data Request
When the user initiates a flow or a validation process, the SDK triggers a presentationRequestCallback
. This callback contains a presentationRequest
object with connection details and the items required for data request details.
Sample Example of presentationRequest
:
{
"contact": {
"displayName": "One37 Solutions, Inc.",
"id": "44bb4ffc-75ec-4549-aa2a-0edb44da5873",
"isConnected": true,
"isTrusted": false,
"logoUrl": "https://cdn.one37id.com/static/images/one37.png"
},
"requestId": "7438a3583df5462cd08563ccce99ccc48a70f62bdd5624cd5c700983f570c5b6",
"isAllowLaterProcessing": true,
"items": [
{
"id": "0192b8be-08cb-788e-99ed-15318c6d319f-driver's-license-(front)",
"name": "Driver's License (Front)",
"purpose": "Driver's License Verification",
"type": "sa",
"availableCredentials": []
},
{
"id": "0192b8be-08cc-788e-99ed-1b37729b8c3c-verified-email",
"name": "Verified Email",
"purpose": "Email Verification",
"type": "vc",
"availableCredentials": [
{
"id": "d574852645dd10dc25a1bd0b8ba34591d9294a536d37b95374c79848a1cfdf7a9e3b5858bb5a641df59aad4d30523229abd0bd689d6b882befb27357bbddf2b5",
"credential": {
"type": "https://137.dev-one37.id/bc/public/schemas/com.one37id.email/1.0",
"issuer": "did:web:137.dev-one37.id",
"issuanceDate": "2024-10-23T09:17:49Z",
"expirationDate": "2029-10-23T09:17:49Z"
}
}
]
},
{
"id": "0192b8be-08cc-788e-99ed-204f1c149711-selfie",
"name": "Selfie",
"purpose": "Selfie Verification",
"type": "sa",
"availableCredentials": []
}
],
"metadata": {
"registration": "eyJpZF90b2tlbl9zaWduaW5nX2FsZ192YWx1ZXNfc3VwcG9ydGVkIjpbIkVkRFNBIiwiRVMyNTYiLCJFUzI1NksiXSwicmVxdWVzdF9vYmplY3Rfc2lnbmluZ19hbGdfdmFsdWVzX3N1cHBvcnRlZCI6WyJFZERTQSIsIkVTMjU2IiwiRVMyNTZLIl0sInJlc3BvbnNlX3R5cGVzX3N1cHBvcnRlZCI6WyJpZF90b2tlbiJdLCJzY29wZXNfc3VwcG9ydGVkIjpbIm9wZW5pZCBkaWRfYXV0aG4iXSwic3ViamVjdF90eXBlc19zdXBwb3J0ZWQiOlsicGFpcndpc2UiXSwic3ViamVjdF9zeW50YXhfdHlwZXNfc3VwcG9ydGVkIjpbImRpZDprZXkiLCJkaWQ6d2ViIiwiZGlkOmp3ayIsImRpZDpwZWVyIl0sInZwX2Zvcm1hdHMiOnsibXNvX21kb2MiOnsiYWxnIjpbIkVkRFNBIiwiRVMyNTYiXX0sImp3dF92YyI6eyJhbGciOlsiRWREU0EiLCJFUzI1NksiXX0sImp3dF92cCI6eyJhbGciOlsiRVMyNTZLIiwiRWREU0EiXX0sInZjK3NkLWp3dCI6eyJzZC1qd3RfYWxnX3ZhbHVlcyI6WyJFUzI1NiJdLCJrYi1qd3RfYWxnX3ZhbHVlcyI6WyJFUzI1NiJdfX0sImNsaWVudF9uYW1lIjoiT25lMzcgU29sdXRpb25zLCBJbmMuIiwiY2xpZW50X2lkIjoiZGlkOndlYjoxMzcuZGV2LW9uZTM3LmlkIn0="
},
"name": "Driver's License verification request",
"purpose": "To verify user's driver's license",
"trustInfo": {
"browser": "not-trust",
"businessIAL": 0,
"network": "ip-match"
}
}
Simplified Version of the Object
The object represents a request for verifying specific credentials made by a contact ("One37 Solutions, Inc."). Here is a breakdown in simpler terms:
-
Contact Information:
- Name: One37 Solutions, Inc.
- Contact ID: A unique ID associated with the contact.
- Connected: Yes (
true
), indicating the system is connected. - Trusted: No (
false
), indicating this contact isn’t marked as trusted. - Logo URL: A link to the contact’s logo image.
-
Request Details:
- Request ID: A unique identifier for the overall request.
- Name: The purpose or name of the request (e.g., "Driver's License Verification Request").
- Allow Later Processing: Indicates whether the request can be processed later (
true
).
-
Items Requested: This section describes the items that need to be provided or verified:
- Available Credentials: A list of credentials that fulfill the item's requirements.
- Type: The type of credential (e.g., a verified credential or self-attested information).
- Purpose: The reason or intent behind requesting this item.
- VerifiableCredential Items: These can be selected from existing verifiable credentials (e.g., an ID issued by a trusted entity). The provided credential data includes details like:
- Credential ID: A unique identifier for the credential.
- Type: The type URL of the credential schema.
- Issuer: The issuer’s unique identifier.
- Issuance Date: The date the credential was issued.
- Expiration Date: When the credential will expire.
- Available Credentials: A list of credentials that fulfill the item's requirements.
-
Trust Information:
- Browser Trust Level: The level of trust assigned to the browser, such as
"not-trust"
. - Network Match: Indicates that the system detected an
"IP Match"
. - Business IAL: Indicates the trust level associated with the business, in this case, 0 (not trusted).
- Browser Trust Level: The level of trust assigned to the browser, such as
-
SelfAttested Items: These require manual submission by the user.
-
VerifiableCredential Items: These can be selected from existing verifiable credentials.
This object is used for handling requests for different types of credentials, allowing the system to verify and approve each item based on available credentials and trust levels.
2. Presenting Data Request to User
The data request is displayed to the user via a custom modal screen that provides a clear overview of all required items and allows them to submit or cancel.
Example:
presentationRequestCallback: async (data: PresentationRequest) => {
const userResponse = await presentProofRequestModalAndWaitForUser(data);
return userResponse;
};
Presenting Data Request Modal
The presentProofRequestModalAndWaitForUser
function displays the data request details, such as the driver's license and selfie, and waits for the user's response.
Once this is called, it takes the user to the ProofRequestScreen
:
describe each action and the response(result or credentials).
Whats the difference between sa and vc, and describe how to handle both of them.
const presentProofRequestModalAndWaitForUser = (
proofItem: PresentationRequest
): Promise<ProofRequestCallbackResponse> => {
return new Promise((resolve) => {
//Sample code
navigateToProofRequestScreen({
title: proofItem.name,
details: proofItem.purpose,
presentationRequst: proofItem
primaryButton: {
caption: "Hold to send",
onPress: (result) => {
resolve({
action: ProofRequestCallbackAction.Send,
response: result,
});
goBack();
},
},
secondaryButton: {
caption: "Cancel",
onPress: () => {
resolve({ action: ProofRequestCallbackAction.Reject, response: [] });
goBack();
},
},
onClose: () => {
resolve({ action: ProofRequestCallbackAction.Later, response: [] });
},
});
});
};
Actions in the Data Request
-
Sending Data (Send):
-
Purpose: The user decides to share the requested data.
-
What Happens: The user clicks on a button to confirm their decision. When this happens, we resolve the action as Send.
-
Response: The response includes the data (result), which contains the selected credentials that the user has chosen to provide.
-
Format:
{
"action": ProofRequestCallbackAction.Send,
"response": result // The result which is the data response
}
-
-
Rejecting Data (Cancel):
-
Purpose: The user chooses not to provide any data.
-
What Happens: When the user clicks "Cancel," we resolve the action as Reject.
-
Response: An empty response array is returned, indicating that no data data is shared.
-
Format:
{
"action": ProofRequestCallbackAction.Reject,
"response": []
}
-
-
Postponing Data (Close):
-
Purpose: The user chooses to handle the data request at a later time.
-
What Happens: If the user closes the modal without taking action, we resolve it as Later.
-
Response: An empty response array, similar to rejecting, indicating that no action has been completed.
-
Format:
{
"action": ProofRequestCallbackAction.Later,
"response": []
}
-
Difference between "sa"
and "vc"
-
Self-Attested (sa): This means the user provides information themselves (e.g., taking a selfie or entering a phone number). There’s no external verification.
- Handling: The user manually submits the data through the app interface.
-
Verifiable Credentials (vc): This means the information comes from a verified source (e.g., a government ID or verified email).
- Handling: The app checks if the user has existing verified credentials. If not, it prompts the user to acquire them through a flow (like connecting to a credential issuer).
Summary of the Process
- If the user selects Send, we include the selected credentials in the response.
- If the user selects Cancel or simply closes the screen (Later), no data is shared, and we handle it as a rejection or postponement accordingly.
3. Acquiring Credentials
Once the data request is presented, the user needs to submit existing verifiable credentials or provide self-attested ones. This is where the handleAcquire
function is utilized.
Example: Acquiring Credentials
const handleAcquire = async (id: string) => {
let updatedData = [...requestData];
const selectedItem = updatedData.find(item => item.id === id);
if (!selectedItem) return;
const agentInstance = await initializeAgent();
if (!agentInstance) {
console.error('Agent instance not found');
return;
}
if (selectedItem.type === RequestedDataValueType.SelfAttested) {
//The function here trigger the cameraActivity callback
const activityResponse = await agentInstance.presentationRequestManager.processPresentationRequestItem(
selectedItem,
presentationRequest?.contact.id,
);
if (activityResponse) {
selectedItem.isAcquired = true;
setRequestData(updatedData);
setResult(prevResult => [
...prevResult,
{ id: id, selected: activityResponse.result! }
]);
}
} else if (selectedItem.type === RequestedDataValueType.VerifiableCredential) {
// Handle verifiable credentials logic
}
};
4. Handling Camera Activity for Self-Attested Credentials
For self-attested credentials, the SDK triggers a cameraActivity
callback when processing the data item, the SDK triggers the cameraActivity
callback when the processPresentationRequestItem
from the presentationRequestManager
is called.
For self-attested
credentials, you need to implement this activity callback handler if it is requires a camera.
Click here to see the camera activity callback.
To see other part of activities click here.
Example:
cameraActivity: async (data) => {
return await new Promise((resolve) => {
navigateToCameraScreen({
onPhotoTaken: (photoUri) => {
resolve({ action: "OK", result: photoUri });
},
});
});
};
Step 5: Processing the Captured Photo
After taking the photo, convert it to base64 for submission:
const takePicture = async () => {
const photo = await cameraRef.current.takePhoto();
const resizedImage = await ImageResizer.createResizedImage(
photo.path,
800,
600,
"JPEG",
60
);
//convert it to base64
const base64Image = await convertToBase64(resizedImage.uri);
handleAccept(base64Image);
};
After capturing and processing all required credentials (e.g., email, driver's license, and selfie), submit the data back to the SDK to complete the verification process.
const handleAccept = async (photoBase64) => {
// Finalize and send the photo or other credential data
onPhotoTaken(photoBase64);
};
This will submit the data request once all the required items have been acquired.
Note that you need to convert the image to base64 when returning it back.
Step 6: Submitting Data Response
After acquiring the necessary credentials, it's time to send them back to the verifier. This is done using the primaryButton?.onPress(result)
method.
Key Points to Keep in Mind:
-
Acquiring Credentials: Acquiring is the process of obtaining new credentials to add to your wallet. This can involve getting verifiable credentials from a trusted source or providing self-attested values if no relevant credential exists in your wallet. This step ensures you have the required credential ready for submission.
-
Selecting a Credential: Once you have acquired credentials or self-attested values, the next step is to choose the most appropriate one from the candidate list. For each requested item, select the relevant credential or self-attested value to match the data requirements.
-
Mandatory Acquired Credentials: If you haven't acquired and selected all the necessary credentials for each requested item, the "Send" action remains disabled. This restriction ensures that the data response is complete and meets all the verifier's requirements.
Example:
const submitCredentials = () => {
// Ensure that all acquired credentials are present
if (result.every((item) => item.selected)) {d
primaryButton?.onPress(result); // Send acquired credentials (data response) to the verifier
} else {
alert("Please acquire all required credentials before submitting.");
}
};
How This Works:
- Acquiring and Selecting Credentials: The app checks if the user has selected a verified credential for each required item (either self-attested or verifiable). If not, it alerts the user to complete all required items.
- Sending Data Response: Once all credentials are acquired and selected, the response is sent to the verifier using the
primaryButton.onPress(result)
method.
This step ensures that users can only submit a complete set of verified credentials, preventing incomplete submissions and ensuring data integrity.
The result
contains all the credentials that were either acquired or selected by the user.
It's an array of objects, each object contains the id
of the item and the selected
which is for example the image base64.
So it will looks something like this:
[
{ "id": "829231931292", "selected": "imageBase64" },
{ "id": "813823818922", "selected": "imageBase64" },
{ "id": "1728391928", "selected": "email" }
]
Conclusion
By following this guide, developers can manage data requests and data responses using the One37ID SDK efficiently. Although this example highlights a specific scenario, the described steps can handle various data requests with different credentials. The data requests in the reponse involves:
- Initiating Data Request: Requesting validation and receiving data items.
- Presenting Data Request: Displaying the required items to the user.
- Acquiring Credentials: Allowing the user to provide credentials manually or select existing ones.
- Sending Data Response: Sending the data response to the verifier.
This standardized process enables efficient validation and credential management across multiple use cases with the SDK.